﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using YonYou.U8.IN.Forms.Win32;

namespace YonYou.U8.IN.Forms
{
    public  class FormBase : Form
    {
        public FormBase()
        {
            InitializeComponent();
            base.SetStyle(ControlStyles.ContainerControl | ControlStyles.UserPaint
                | ControlStyles.ResizeRedraw | ControlStyles.Selectable | ControlStyles.AllPaintingInWmPaint
                | ControlStyles.OptimizedDoubleBuffer, true);
            base.SetStyle(ControlStyles.Opaque, false);
            base.UpdateStyles();
            this.Initialize();
        }
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // FormBase
            // 
            this.ClientSize = new System.Drawing.Size(449, 263);
            this.Name = "FormBase";
            this.ResumeLayout(false);

        }
        protected override void Dispose(bool disposing)
        {
            if (this._BufferImage != null)
            {
                this._BufferImage.Dispose();
            }
            base.Dispose(disposing);
            //if (this._WndShadow != null)
            //{
            //    this._WndShadow.Dispose();
            //    this._WndShadow = null;
            //}
        }
        /// <summary>
        /// 标题栏高度
        /// </summary>
        public const int TitleBarHeight = 30;
        // 标题栏背景渐变起始颜色
        private Color _titleBarStartColor=Color.FromArgb(72, 144, 228);
        // 标题栏背景渐变结束颜色
        private Color _titleBarEndColor = Color.FromArgb(60, 128, 212);

        /// <summary>
        /// 获取或设置窗体标题栏的渐变起始颜色。
        /// </summary>
        [Browsable(true)]
        [Category("Wade")]
        [Description("获取或设置窗体标题栏的渐变起始颜色。")]
        [DefaultValue(typeof(Color), "72,144,228")]
        public Color TitleBarStartColor
        {
            get
            {
                return _titleBarStartColor;
            }

            set
            {
                _titleBarStartColor = value;
                DrawTitleBar();
            }
        }

        /// <summary>
        /// 获取或设置窗体标题栏的渐变结束颜色。
        /// </summary>
        [Browsable(true)]
        [Category("Wade")]
        [Description("获取或设置窗体标题栏的渐变结束颜色。")]
        [DefaultValue(typeof(Color), "60, 128, 212")]
        public Color TitleBarEndColor
        {
            get
            {
                return _titleBarEndColor;
            }

            set
            {
                _titleBarEndColor = value;
                DrawTitleBar();
            }
        }
        // 边框样式
        private FormBorderStyle _formBorderStyle = FormBorderStyle.Sizable;
        /// <summary>
        /// 获取或设置窗体的边框样式。
        /// </summary>
        [Browsable(true)]
        [Category("Wade")]
        [Description("获取或设置窗体的边框样式。")]
        [DefaultValue(FormBorderStyle.Sizable)]
        public new FormBorderStyle FormBorderStyle
        {
            get { return _formBorderStyle; }
            set
            {
                _formBorderStyle = value;
                UpdateStyles();
                DrawTitleBar();
            }
        }
        /// <summary>
        /// 绘制标题栏
        /// </summary>
        private void DrawTitleBar()
        {
            if (_formBorderStyle == FormBorderStyle.None)
                return;
            //DrawTitleBackgroundTextIcon();
            //CreateButtonImages();
            //DrawTitleButtons();
        }
        protected SysButton _sysButton = SysButton.Normal;

        protected MouseState _closeState = MouseState.Normal;

        protected MouseState _maxState = MouseState.Normal;

        protected MouseState _minState = MouseState.Normal;

        protected Size _formSize = Size.Empty;

        protected Point _formPoint = Point.Empty;

        protected FormWindowState _windowState = FormWindowState.Normal;

        protected bool _isResize = true;

        protected bool _showIcon = true;

        private bool _isTransfer = false;

        private ColorBlend m_Blend;

        private ToolTipRenderer tipRenderer;

        private Bitmap _BufferImage = null;

        private MetroSkin _MetroSkin = new MetroSkin();

        //private WindowShadow _WndShadow;

        private bool isApplyShadow = false;
      
        public delegate void TipDelegate(SysButtonType type);
        [Category("Wade")]
        [Description("是否允许改变窗口大小")]
        [DefaultValue(true)]
        public virtual bool IsResize
        {
            get
            {
                return this._isResize;
            }
            set
            {
                this._isResize = value;
            }
        }
        [Category("Wade")]
        [Description("指定窗体窗口如何显示")]
        public new virtual FormWindowState WindowState
        {
            get
            {
                return base.WindowState;
            }
            set
            {
                switch (value)
                {
                    case FormWindowState.Normal:
                        base.WindowState = FormWindowState.Normal;
                        break;
                    case FormWindowState.Minimized:
                        base.WindowState = FormWindowState.Minimized;
                        break;
                    case FormWindowState.Maximized:
                        this._formSize = base.Size;
                        this._formPoint = base.Location;
                        base.Location = new Point(0, 0);
                        base.Width = Screen.PrimaryScreen.WorkingArea.Width;
                        base.Height = Screen.PrimaryScreen.WorkingArea.Height;
                        base.WindowState = FormWindowState.Maximized;
                        break;
                }
            }
        }
        public override Size MinimumSize
        {
            get
            {
                return new Size(140, 40);
            }
            set
            {
                base.MinimumSize = value;
            }
        }
        public bool IsTransfer
        {
            get
            {
                return this._isTransfer;
            }
            set
            {
                this._isTransfer = value;
            }
        }
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams result;
                if (!this._isTransfer)
                {
                    CreateParams createParams = base.CreateParams;
                    createParams.Style |= Constants.WS_MINIMIZEBOX;
                    createParams.ClassStyle |= Constants.CS_DBLCLKS;
                    result = createParams;
                }
                else
                {
                    CreateParams createParams = base.CreateParams;
                    createParams.ExStyle = 524288;
                    createParams.Style |= Constants.WS_MINIMIZEBOX;
                    createParams.ClassStyle |= Constants.CS_DBLCLKS;
                    result = createParams;
                }
                return result;
            }
        }

        public new virtual bool ShowIcon
        {
            get
            {
                return this._showIcon;
            }
            set
            {
                this._showIcon = value;
                base.Invalidate(this.TitleBarRect);
            }
        }
        public ColorBlend Blend { get; set; }
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
                base.Invalidate(this.TitleBarRect);
            }
        }
        [Category("Wade")]
        [Description("系统控制按钮的显示与隐藏")]
        public SysButton SysButton
        {
            get
            {
                return this._sysButton;
            }
            set
            {
                this._sysButton = value;
                base.Invalidate(this.TitleBarRect);
            }
        }
        protected virtual Rectangle SysBtnRect
        {
            get
            {
                return Rectangle.Empty;
            }
        }
        protected virtual Rectangle TitleBarRect
        {
            get
            {
                return new Rectangle(0, 0, base.Width, 30);
            }
        }
        protected virtual Rectangle CloseRect
        {
            get
            {
                return Rectangle.Empty;
            }
        }
        protected virtual Rectangle MiniRect
        {
            get
            {
                return Rectangle.Empty;
            }
        }
        protected virtual Rectangle MaxRect
        {
            get
            {
                return Rectangle.Empty;
            }
        }
        protected virtual Rectangle IconRect
        {
            get
            {
                return new Rectangle(4, 4, 16, 16);
            }
        }
        protected virtual Rectangle TextRect
        {
            get
            {
                int width = this.TitleBarRect.Width - this.IconRect.Width - 15;
                int height = this.TitleBarRect.Height - 10;
                Rectangle result = new Rectangle(8, 4, width, height);
                if (this.ShowIcon)
                {
                    result.X = this.IconRect.Width + 8;
                }
                return result;
            }
        }
        protected MouseState CloseState
        {
            get
            {
                return this._closeState;
            }
            set
            {
                this._closeState = value;
                base.Invalidate(this.CloseRect);
            }
        }

        protected MouseState MaxState
        {
            get
            {
                return this._maxState;
            }
            set
            {
                this._maxState = value;
                base.Invalidate(this.MaxRect);
            }
        }

        protected MouseState MinState
        {
            get
            {
                return this._minState;
            }
            set
            {
                this._minState = value;
                base.Invalidate(this.MiniRect);
            }
        }

        public MetroSkin MetroSkin
        {
            get
            {
                return this._MetroSkin;
            }
            set
            {
                this._MetroSkin = value;
            }
        }

        protected Size FormSize
        {
            get
            {
                return this._formSize;
            }
        }

        protected Point FormPoint
        {
            get
            {
                return this._formPoint;
            }
        }
        private void Initialize()
        {
            this.tipRenderer = new ToolTipRenderer(this);
            this.m_Blend = new ColorBlend();
            Color[] colors = new Color[]
            {
                ColorTranslator.FromHtml("#ffff"),
                ColorTranslator.FromHtml("#d000"),
                ColorTranslator.FromHtml("#f683CA")
            };
            float[] positions = new float[]
            {
                0f,
                0.1f,
                1f
            };
            this.m_Blend.Colors = colors;
            this.m_Blend.Positions = positions;
            base.FormBorderStyle = FormBorderStyle.None;
        }
        private void InitWindowShadow()
        {
            if (!this.isApplyShadow && !base.DesignMode)
            {
                //WindowShadow.Initialize();
                //this._WndShadow = new WindowShadow();
                //this._WndShadow.Create(this);
                this.isApplyShadow = true;
            }
        }
        private void WmNcHitTest(ref Message m)
        {
            if (this.WindowState != FormWindowState.Maximized)
            {
                int value = m.LParam.ToInt32();
                Point p = new Point(NativeMethods.LOWORD(value), NativeMethods.HIWORD(value));
                p = base.PointToClient(p);
                if (this._isResize)
                {
                    if (p.X <= 3)
                    {
                        if (p.Y <= 3)
                        {
                            m.Result = (IntPtr)13L;
                        }
                        else if (p.Y > base.Height - 3)
                        {
                            m.Result = (IntPtr)16L;
                        }
                        else
                        {
                            m.Result = (IntPtr)10L;
                        }
                    }
                    else if (p.X >= base.Width - 3)
                    {
                        if (p.Y <= 3)
                        {
                            m.Result = (IntPtr)14L;
                        }
                        else if (p.Y >= base.Height - 3)
                        {
                            m.Result = (IntPtr)17L;
                        }
                        else
                        {
                            m.Result = (IntPtr)11L;
                        }
                    }
                    else if (p.Y <= 3)
                    {
                        m.Result = (IntPtr)12L;
                    }
                    else if (p.Y >= base.Height - 3)
                    {
                        m.Result = (IntPtr)15L;
                    }
                    else
                    {
                        base.WndProc(ref m);
                    }
                }
                else
                {
                    base.WndProc(ref m);
                }
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            this.InitWindowShadow();
            base.OnPaint(e);
            Graphics graphics = e.Graphics;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
            if (this.ShowIcon)
            {
                Bitmap image = base.Icon.ToBitmap();
                graphics.DrawImage(image, this.IconRect);
            }
            if (!string.IsNullOrEmpty(this.Text))
            {
                TextRenderer.DrawText(graphics, this.Text, this.Font, this.TextRect, this.ForeColor, TextFormatFlags.VerticalCenter);
            }
        }
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);
            if (this.MetroSkin != null)
            {
                using (Brush brush = new SolidBrush(this.MetroSkin.BackColor))
                {
                    e.Graphics.FillRectangle(brush, base.ClientRectangle);
                }
            }
            else
            {
                using (LinearGradientBrush linearGradientBrush = new LinearGradientBrush(base.ClientRectangle, this.m_Blend.Colors[0], this.m_Blend.Colors[this.m_Blend.Colors.Length - 1], LinearGradientMode.Vertical))
                {
                    linearGradientBrush.WrapMode = WrapMode.TileFlipXY;
                    linearGradientBrush.InterpolationColors = this.m_Blend;
                    e.Graphics.FillRectangle(linearGradientBrush, base.ClientRectangle);
                }
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            base.MaximizedBounds = Screen.PrimaryScreen.WorkingArea;
            if (!base.DesignMode)
            {
                switch (base.StartPosition)
                {
                    case FormStartPosition.CenterScreen:
                        base.Location = new Point((Screen.PrimaryScreen.WorkingArea.Width - base.Width) / 2, (Screen.PrimaryScreen.WorkingArea.Height - base.Height) / 2);
                        break;
                    case FormStartPosition.CenterParent:
                        if (base.Parent != null)
                        {
                            base.Location = new Point((base.Parent.Width - base.Width) / 2, (base.Parent.Height - base.Height) / 2);
                        }
                        break;
                }
            }
            this.InitWindowShadow();
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            base.Padding = new Padding(1, 30, 1, 1);
        }

        protected override void WndProc(ref Message m)
        {
            try
            {
                int msg = m.Msg;
                if (msg != 3)
                {
                    switch (msg)
                    {
                        case 131:
                        case 133:
                            break;
                        case 132:
                            base.WndProc(ref m);
                            this.WmNcHitTest(ref m);
                            break;
                        case 134:
                            if (m.WParam == (IntPtr)0)
                            {
                                m.Result = (IntPtr)1;
                            }
                            break;
                        default:
                            if (msg != 562)
                            {
                                base.WndProc(ref m);
                            }
                            else
                            {
                                //if (this._WndShadow != null)
                                //{
                                //    this._WndShadow.HandleWmMessage(this, (uint)m.Msg);
                                //}
                                base.WndProc(ref m);
                            }
                            break;
                    }
                }
                else
                {
                    //if (this._WndShadow != null)
                    //{
                    //    this._WndShadow.HandleWmMessage(this, (uint)m.Msg);
                    //}
                    base.WndProc(ref m);
                }
            }
            catch
            {
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            Point location = e.Location;
            if (e.Button == MouseButtons.Left)
            {
                if (this.CloseRect.Contains(location))
                {
                    this.CloseState = MouseState.Down;
                }
                else if (this.MiniRect.Contains(location))
                {
                    this.MinState = MouseState.Down;
                }
                else if (this.MaxRect.Contains(location))
                {
                    this.MaxState = MouseState.Down;
                }
            }
            if (this.WindowState != FormWindowState.Maximized)
            {
                if (e.Button == MouseButtons.Left && !this.SysBtnRect.Contains(e.Location))
                {
                    NativeMethods.ReleaseCapture();
                    NativeMethods.SendMessage(base.Handle, 274, 61449, 0);
                }
            }
            if (!this.SysBtnRect.Contains(e.Location) && e.Clicks == 2 && this.TitleBarRect.Contains(e.Location))
            {
                this.OnWindowState();
            }
        }

        protected virtual void OnWindowState()
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                base.Size = this._formSize;
                base.Location = this._formPoint;
                this.WindowState = FormWindowState.Normal;
            }
            else if (this.WindowState == FormWindowState.Normal)
            {
                this.WindowState = FormWindowState.Maximized;
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.Button != MouseButtons.Left)
            {
                Point location = e.Location;
                SysButtonType type = SysButtonType.None;
                if (this.CloseRect.Contains(location))
                {
                    this.CloseState = MouseState.Move;
                    type = SysButtonType.CloseButton;
                }
                else
                {
                    this.CloseState = MouseState.Normal;
                }
                if (this.MiniRect.Contains(location))
                {
                    this.MinState = MouseState.Move;
                    type = SysButtonType.MinButton;
                }
                else
                {
                    this.MinState = MouseState.Normal;
                }
                if (this.SysButton == SysButton.Normal)
                {
                    if (this.MaxRect.Contains(location))
                    {
                        this.MaxState = MouseState.Move;
                        if (this.WindowState == FormWindowState.Maximized)
                        {
                            type = SysButtonType.RestoreButton;
                        }
                        else
                        {
                            type = SysButtonType.MaxButton;
                        }
                    }
                    else
                    {
                        this.MaxState = MouseState.Normal;
                    }
                }
                this.SysButtonTipHandle(type, e.X, e.Y);
            }
        }

        protected void SysButtonTipHandle(SysButtonType type, int x, int y)
        {
            this.tipRenderer.Show(type);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            this.CloseState = MouseState.Normal;
            this.MaxState = MouseState.Normal;
            this.MinState = MouseState.Normal;
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (e.Button == MouseButtons.Left)
            {
                Point location = e.Location;
                if (this.CloseRect.Contains(location))
                {
                    this.CloseState = MouseState.Move;
                    base.Close();
                }
                else
                {
                    this.CloseState = MouseState.Normal;
                    if (this.MiniRect.Contains(location))
                    {
                        this.MinState = MouseState.Move;
                        this.WindowState = FormWindowState.Minimized;
                    }
                    else
                    {
                        this.MinState = MouseState.Normal;
                    }
                    if (this.MaxRect.Contains(location))
                    {
                        this.MaxState = MouseState.Move;
                        if (this.WindowState == FormWindowState.Maximized)
                        {
                            base.Size = this._formSize;
                            base.Location = this._formPoint;
                            this.WindowState = FormWindowState.Normal;
                        }
                        else
                        {
                            this.WindowState = FormWindowState.Maximized;
                        }
                    }
                    else
                    {
                        this.MaxState = MouseState.Normal;
                    }
                }
            }
        }
        private class ToolTipRenderer
        {
            private Form window = null;
            private MetroToolTip tip = null;
            private IDictionary<SysButtonType, string> tipDics = new Dictionary<SysButtonType, string>();
            private SysButtonType type = SysButtonType.None;
            public ToolTipRenderer(Form form)
            {
                this.window = form;
                this.InitTipDic();
            }

            private void InitTipDic()
            {
                this.tipDics.Add(SysButtonType.MinButton, "最小化");
                this.tipDics.Add(SysButtonType.MaxButton, "最大化");
                this.tipDics.Add(SysButtonType.RestoreButton, "向下还原");
                this.tipDics.Add(SysButtonType.CloseButton, "关闭");
            }

            public void Show(SysButtonType type)
            {
                if (type != this.type || this.tip == null)
                {
                    if (type == SysButtonType.None)
                    {
                        this.type = type;
                        if (this.tip != null)
                        {
                            this.tip.Dispose();
                            this.tip = null;
                        }
                    }
                    else if (this.tip == null && type != SysButtonType.None && this.tipDics.ContainsKey(type))
                    {
                        this.type = type;
                        this.tip = new MetroToolTip();
                        this.tip.Hide(this.window);
                        this.tip.SetToolTip(this.window, this.tipDics[type]);
                    }
                    else if (this.tip != null && type != SysButtonType.None && this.tipDics.ContainsKey(type))
                    {
                        this.type = type;
                        this.tip.Dispose();
                        this.tip = null;
                        this.tip = new MetroToolTip();
                        this.tip.Hide(this.window);
                        this.tip.SetToolTip(this.window, this.tipDics[type]);
                    }
                }
            }


        }
    }
}